﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using IdentityModel.AspNetCore.OAuth2Introspection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;


//using JetBrains.Annotations;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class AbpSwaggerGenExtensions
    {
        private static string title = string.Empty;
        private static string version = string.Empty;
        private static string authority = string.Empty;
        private static bool requireHttps = false;
        private static string apiName = string.Empty;
        private static Dictionary<string, string> scopes = new();

        private static void Init(IConfiguration configuration)
        {
            title = configuration["AuthServer:Title"] ?? string.Empty;
            version = configuration["AuthServer:Version"] ?? "v1";
            authority = configuration["AuthServer:Authority"] ?? string.Empty;
            requireHttps = Convert.ToBoolean(configuration["AuthServer:RequirehttpssMetadata"] ?? "false");
            apiName = configuration["AuthServer:ApiName"] ?? "";
            if (!string.IsNullOrWhiteSpace(configuration["AuthServer:Scopes"]))
            {
                var scope_list = configuration["AuthServer:Scopes"].Split(",", StringSplitOptions.RemoveEmptyEntries).Distinct();
                var dic = new Dictionary<string, string>();
                foreach (var scope in scope_list)
                    dic.Add(scope, $"swagger访问 [{scope}]");

                scopes = dic;
            }
        }

        public static IServiceCollection AddAbpSwaggerGenWithOAuth2(this IServiceCollection services,
                                                                   [NotNull] IConfiguration configuration,
                                                                   List<string> xmls,
                                                                   Action<SwaggerGenOptions> setupAction = null,
                                                                   OpenApiOAuthFlows oAuthFlows = null)
        {
            Init(configuration);
            services.AddAuthentication("Bearer")
            .AddIdentityServerAuthentication(options =>
            {
                options.JwtBackChannelHandler = new HttpClientHandler
                {
                    ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
                };
                options.Authority = authority;
                options.ApiName = apiName;
                options.RequireHttpsMetadata = requireHttps;


                options.Events = new OAuth2IntrospectionEvents()
                {
                    OnTokenValidated = (tokenValidatedContext) =>
                    {

                        if (tokenValidatedContext.Result.Succeeded)
                        {
                            tokenValidatedContext.HttpContext.Response.Redirect("www.baidu.com");
                        }
                        return Task.CompletedTask;
                    }
                };
            });

            return services.AddSwaggerGen(options =>
                {
                    options.SwaggerDoc(version, new OpenApiInfo
                    {
                        Title = title,
                        Version = version,
                        Description = "backend-admin-app-client-1q2w3E*-"

                    });
                    options.DocInclusionPredicate((docName, description) => true);
                    var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
                    foreach (var xml in xmls)
                    {
                        if (File.Exists(Path.Combine(baseDirectory, xml)))
                            options.IncludeXmlComments(Path.Combine(baseDirectory, xml), true);
                        else
                            Console.WriteLine($"swagger未找到XmlComment：{Path.Combine(baseDirectory, xml)}");
                    }
                    oAuthFlows ??= new OpenApiOAuthFlows
                    {
                        //Implicit = new OpenApiOAuthFlow
                        //{

                        //    TokenUrl = new Uri($"{authority}/connect/token"),
                        //    AuthorizationUrl = new Uri($"{authority}/connect/authorize"),

                        //    Scopes = scopes
                        //},
                        Password = new OpenApiOAuthFlow
                        {
                            TokenUrl = new Uri($"{authority}/connect/token"),
                            AuthorizationUrl = new Uri($"{authority}/connect/authorize"),
                            Scopes = scopes
                        }
                    };
                    options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                    {
                        Type = SecuritySchemeType.OAuth2,
                        Flows = oAuthFlows,
                        Description = "backend-admin-app-client-1q2w3E*"
                    });

                    options.AddSecurityRequirement(new OpenApiSecurityRequirement
                    {
                        {
                            new OpenApiSecurityScheme
                            {
                                Reference = new OpenApiReference
                                {
                                    Type = ReferenceType.SecurityScheme,
                                    Id = "oauth2"
                                }
                            },
                            Array.Empty<string>()
                        }
                    });
                    if (options != null)
                        setupAction?.Invoke(options);
                });
        }
    }
}
